using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using ProjectEuler.Core.Helpers;

namespace ProjectEuler.Core
{
    public class Problem27 : IProjectEulerProblem
    {
        public int Number
        {
            get { return 27; }
        }

        public string Description
        {
            get
            {
                return "Find the product of the coefficients, a and b, for the quadratic expression that produces the maximum number of primes for consecutive values of n, starting with n = 0.";
            }
        }

        public string Answer
        {
            get
            {
                var quads = QuadraticsOfForm(1000).OrderByDescending(x => x.MaximumNumberConsecutivePrimes).ToList();
                var quad = quads.First();
                return (quad.AtimesB).ToString();
            }
        }

        public class Quadratic
        {
            public int A { get; private set; }
            public int B { get; private set; }
            public Quadratic(int A, int B)
            {
                this.A = A;
                this.B = B;
            }

            public int Evaluate(int n)
            {
                return (n*n) + (A*n) + B;
            }

            public int MaximumNumberConsecutivePrimes
            {
                get
                {
                    var consecutivePrimes = 0;
                    var n = 0;
                    while (MathHelper.IsPrime(Evaluate(n)))
                    {
                        n++;
                        consecutivePrimes++;
                    }
                    return consecutivePrimes;
                }
            }

            public int AtimesB
            {
                get
                {
                    return A * B;
                }
            }
        }

        protected IList<Quadratic> QuadraticsOfForm(int n)
        {
            var list = new List<Quadratic>();
            for (int i = (-n+1); i < n; i++)
            {
                for (int j = (-n+1); j < n; j++)
                {
                    list.Add(new Quadratic(i, j));
                }
            }
            return list;
        }
    }

    [TestFixture]
    public class Problem27Tests : Problem27
    {
        [Test]
        public void Eulers_prime_formula_should_produce_40_consecutive_primes()
        {
            var quad = new Quadratic(1, 41);
            Assert.AreEqual(40, quad.MaximumNumberConsecutivePrimes);
        }

        [Test]
        public void Computers_prime_formula_should_produce_80_consecutive_primes()
        {
            var quad = new Quadratic(-79, 1601);
            Assert.AreEqual(80, quad.MaximumNumberConsecutivePrimes);
        }

        [Test]
        public void Neg1935_shouldnt_be_prime()
        {
            Assert.IsFalse(MathHelper.IsPrime(-1935));
        }
    }
}